package controllers

import (
	"GoWeb_Advanced/00_bluebell/dao/mysql"
	"GoWeb_Advanced/00_bluebell/logic"
	"GoWeb_Advanced/00_bluebell/models"
	"errors"
	"fmt"

	"github.com/go-playground/validator/v10"

	"go.uber.org/zap"

	"github.com/gin-gonic/gin"
)

// SignUpHandler 处理注册请求的函数
func SignUpHandler(ctx *gin.Context) {
	//1.获取参数和参数校验
	p := new(models.ParamSignUp)
	//ShouldBindJSON 只能对字段类型（如该字段是否是对应的（string/int..）类型）、请求数据的格式（如是否是json格式）进行校验
	if err := ctx.ShouldBindJSON(p); err != nil {
		//请求参数有误，直接返回响应
		zap.L().Error("SignUp with invalid param", zap.Error(err))
		//判断 err 是不是 validator.ValidationErrors 类型（gin 框架中的错误）
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			ResponseError(ctx, CodeInvalidParam)
			return
		}
		ResponseErrorWithMsg(ctx, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
		return
	}
	//手动对请求参数进行详细的业务规则校验（不要相信前端，无论何时，后端都要进行参数的校验）
	//if len(p.Username) == 0 || len(p.Password) == 0 || len(p.RePassword) == 0 || p.RePassword != p.Password {
	//	//请求参数错误，直接返回响应
	//	zap.L().Error("SignUp with invalid param")
	//	ctx.JSON(http.StatusOK, gin.H{
	//		"msg": "请求参数有误",
	//	})
	//	return
	//}
	//2.业务处理
	if err := logic.SignUp(p); err != nil {
		zap.L().Error("logic.SignUp failed, err:", zap.Error(err))
		if errors.Is(err, mysql.ErrorUserExist) {
			ResponseError(ctx, CodeUserExist)
		}
		ResponseError(ctx, CodeServerBusy)
		return
	}
	//3.返回响应
	ResponseSuccess(ctx, nil)
}

// LoginHandler 处理登录请求的函数
func LoginHandler(ctx *gin.Context) {
	//1.获取请求参数和校验参数
	p := new(models.ParamLogin)
	if err := ctx.ShouldBindJSON(p); err != nil {
		//请求参数有误，直接返回响应
		zap.L().Error("Login with invalid param, err:", zap.Error(err))
		//判断 err 是不是 validator.ValidationErrors 类型的 err
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			ResponseError(ctx, CodeInvalidParam)
			return
		}
		ResponseErrorWithMsg(ctx, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
		return
	}
	//2.业务处理
	user, err := logic.Login(p)
	if err != nil {
		zap.L().Error("logic.Login failed, err:", zap.String("username", p.Username), zap.Error(err))
		if errors.Is(err, mysql.ErrorUserNotExist) {
			ResponseError(ctx, CodeUserNotExist)
			return
		}
		ResponseError(ctx, CodeInvalidPassword)
		return
	}
	//3.返回响应
	ResponseSuccess(ctx, gin.H{
		/*
			js中数字的最大范围是 -(2^53-1)到 2^53-1之间，而int64类型的数据的范围是 -(2^63-1)到 2^63-1 之间。
			为了防止后端传送给前端的 id 值会超过 js 所限定的最大值，导致数据失真，
			我们将 id 值转化为 string类型 之后，在传送给 前端 会比较好
		*/
		"user_id":   fmt.Sprintf("%d", user.UserID), //id 值大于 1 << 53-1； int64类型的最大值是 1<<63-1（js中数字的最大范围是 -(2^53-1)到 2^53-1之间）
		"user_name": user.Username,
		"token":     user.Token,
	})
}
